package org.jing.ext.extra;

import org.jing.core.lang.JingException;
import org.jing.core.util.ClassUtil;
import org.jing.core.util.GenericUtil;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Description: 简繁互转 <br>
 *
 * @author bks <br>
 * @since 2023-04-13 <br>
 */
public class ZHConverter {
    private Properties charMap = new Properties();

    private final Set<String> conflictingSets = new HashSet<>();

    public static final int CHT = 0;

    public static final int CHS = 1;

    private static final ZHConverter[] CONVERTERS = new ZHConverter[2];

    private static final String[] propertyFiles = new String[]{"cht.properties", "chs.properties"};

    public static ZHConverter getInstance(int converterType) {
        if (null == CONVERTERS[converterType]) {
            synchronized (ZHConverter.class) {
                if (null == CONVERTERS[converterType]) {
                    switch (converterType) {
                        case CHT:
                        case CHS:
                            ClassLoader[] classLoaders = ClassUtil.getClassLoader(ZHConverter.class);
                            ClassLoader classLoader;
                            boolean loaded = false;
                            InputStream is;
                            ZHConverter converter = new ZHConverter();
                            for (int i$ = 0, s$ = GenericUtil.count(classLoaders); i$ < s$; i$ ++) {
                                classLoader = classLoaders[i$];
                                if (null != classLoader) {
                                    is = classLoader.getResourceAsStream(propertyFiles[converterType]);
                                    if (null != is) {
                                        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
                                            converter.charMap = new Properties();
                                            converter.charMap.load(reader);
                                            loaded = true;
                                        }
                                        catch (JingException e) {
                                            throw e;
                                        }
                                        catch (Throwable t) {
                                            throw new JingException(t);
                                        }
                                    }
                                }
                            }
                            if (!loaded) {
                                throw new JingException("failed to load resource: {]", propertyFiles[converterType]);
                            }
                            converter.initializeHelper();
                            CONVERTERS[converterType] = converter;
                            break;
                        default:
                            throw new JingException("invalid converter type: {}", converterType);
                    }
                }
            }
        }
        return CONVERTERS[converterType];
    }

    private ZHConverter() {}

    private void initializeHelper() {
        Map<String, Integer> stringPossibilities = new HashMap<>();
        Iterator iter = this.charMap.keySet().iterator();
        while(true) {
            String key;
            do {
                if (!iter.hasNext()) {
                    iter = stringPossibilities.keySet().iterator();
                    while(iter.hasNext()) {
                        key = (String) iter.next();
                        if ((stringPossibilities.get(key)) > 1) {
                            this.conflictingSets.add(key);
                        }
                    }
                    return;
                }
                key = (String)iter.next();
            }
            while(key.isEmpty());
            for (int i$ = 0; i$ < key.length(); ++ i$) {
                String keySubstring = key.substring(0, i$ + 1);
                if (stringPossibilities.containsKey(keySubstring)) {
                    stringPossibilities.put(keySubstring, stringPossibilities.get(keySubstring) + 1);
                } else {
                    stringPossibilities.put(keySubstring, 1);
                }
            }
        }
    }

    public static String convert(String in, int convertType) {
        return getInstance(convertType).convert(in);
    }

    public String convert(String in) {
        StringBuilder outString = new StringBuilder();
        StringBuilder stackString = new StringBuilder();

        for(int i = 0; i < in.length(); ++i) {
            stackString.append(in.charAt(i));
            if (!this.conflictingSets.contains(stackString.toString())) {
                if (this.charMap.containsKey(stackString.toString())) {
                    outString.append(this.charMap.get(stackString.toString()));
                    stackString.setLength(0);
                } else {
                    CharSequence sequence = stackString.subSequence(0, stackString.length() - 1);
                    stackString.delete(0, stackString.length() - 1);
                    this.flushStack(outString, new StringBuilder(sequence));
                }
            }
        }

        this.flushStack(outString, stackString);
        return outString.toString();
    }

    private void flushStack(StringBuilder outString, StringBuilder stackString) {
        while(stackString.length() > 0) {
            if (this.charMap.containsKey(stackString.toString())) {
                outString.append(this.charMap.get(stackString.toString()));
                stackString.setLength(0);
            } else {
                outString.append(stackString.charAt(0));
                stackString.delete(0, 1);
            }
        }
    }

    private void init() {

    }

    public static void main(String[] args) {
        String content = "阿薩請額讓圖與";
        System.out.println(content = ZHConverter.convert(content, ZHConverter.CHS));
        System.out.println(content = ZHConverter.convert(content, ZHConverter.CHT));
    }
}
